package com.zenithmind.note.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zenithmind.note.mapper.NoteMapper;
import com.zenithmind.note.pojo.dto.NoteDTO;
import com.zenithmind.note.pojo.entity.Note;
import com.zenithmind.note.pojo.entity.NoteLike;
import com.zenithmind.note.pojo.entity.NoteTag;
import com.zenithmind.note.pojo.entity.NoteTagRelation;
import com.zenithmind.note.pojo.query.NoteQuery;
import com.zenithmind.note.pojo.vo.NoteVO;
import com.zenithmind.note.pojo.vo.NoteTagVO;
import com.zenithmind.note.service.NoteService;
import com.zenithmind.note.service.NoteLikeService;
import com.zenithmind.note.service.NoteTagService;
import com.zenithmind.note.service.NoteTagRelationService;
import com.zenithmind.common.result.PageResult;
import com.zenithmind.common.exception.UnauthorizedException;
import com.zenithmind.common.annotation.DataCache;
import com.zenithmind.common.annotation.DataCacheEvict;
import com.zenithmind.common.constant.CacheConstants;
import com.zenithmind.common.utils.RedisUtils;
import com.zenithmind.common.security.SecurityUtils;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import lombok.extern.slf4j.Slf4j;

import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.HashMap;
import java.util.ArrayList;
import java.util.concurrent.TimeUnit;

/**
 * 笔记服务实现类
 */
@Service
@Slf4j
public class NoteServiceImpl extends ServiceImpl<NoteMapper, Note> implements NoteService {
    
    @Autowired
    private NoteLikeService noteLikeService;
    
    @Autowired
    private RedisUtils redisUtils;
    
    @Autowired
    private NoteTagService noteTagService;
    
    @Autowired
    private NoteTagRelationService noteTagRelationService;
    
    // 缓存相关常量
    private static final String CACHE_NOTE_PREFIX = "note";
    private static final String CACHE_NOTE_TAGS_KEY = "tags";
    
    /**
     * 创建笔记
     */
    @Override
    @Transactional
    @DataCacheEvict(prefix = CACHE_NOTE_PREFIX, allEntries = true)
    public Note createNote(NoteDTO noteDTO) {
        // 从SecurityUtils获取用户ID
        String userId = SecurityUtils.getCurrentUserId();
        if (StringUtils.isBlank(userId)) {
            throw new UnauthorizedException("用户未登录");
        }
        noteDTO.setUserId(userId);
        
        Note note = new Note();
        BeanUtils.copyProperties(noteDTO, note);
        note.setViewCount(0);
        note.setLikeCount(0);
        note.setCommentCount(0);
        save(note);
        
        // 处理标签关联
        if (noteDTO.getTagIds() != null && !noteDTO.getTagIds().isEmpty()) {
            noteTagRelationService.setNoteTags(note.getId(), noteDTO.getTagIds());
        }
        
        return note;
    }
    
    /**
     * 更新笔记
     */
    @Override
    @Transactional
    @DataCacheEvict(prefix = CACHE_NOTE_PREFIX, key = "#noteDTO.id")
    public void updateNote(NoteDTO noteDTO) {
        // 从SecurityUtils获取用户ID
        String userId = SecurityUtils.getCurrentUserId();
        if (StringUtils.isBlank(userId)) {
            throw new UnauthorizedException("用户未登录");
        }
        noteDTO.setUserId(userId);
        
        Note note = getById(noteDTO.getId());
        if (note == null) {
            throw new RuntimeException("笔记不存在");
        }
        BeanUtils.copyProperties(noteDTO, note);
        updateById(note);
        
        // 处理标签关联
        if (noteDTO.getTagIds() != null) {
            noteTagRelationService.setNoteTags(note.getId(), noteDTO.getTagIds());
        }
    }
    
    /**
     * 删除笔记
     */
    @Override
    @Transactional
    @DataCacheEvict(prefix = CACHE_NOTE_PREFIX, key = "#id")
    public void deleteNote(String id) {
        // 从SecurityUtils获取用户ID验证权限
        String userId = SecurityUtils.getCurrentUserId();
        if (StringUtils.isBlank(userId)) {
            throw new UnauthorizedException("用户未登录");
        }
        
        // 删除笔记
        removeById(id);
        // 删除相关的点赞记录
        LambdaQueryWrapper<NoteLike> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(NoteLike::getNoteId, id);
        noteLikeService.remove(wrapper);
        
        // 删除标签关联
        noteTagRelationService.deleteByNoteId(id);
    }
    
    /**
     * 获取笔记详情 - 内部获取当前用户ID
     */
    @Override
    @DataCache(prefix = CACHE_NOTE_PREFIX, key = "#id", expireTime = CacheConstants.TTL_SECONDS_ARTICLE)
    public NoteVO getNoteDetail(String id) {
        // 直接在方法内获取用户ID
        String userId = SecurityUtils.getCurrentUserId();
        if (StringUtils.isBlank(userId)) {
            throw new UnauthorizedException("用户未登录");
        }
        
        Note note = getById(id);
        if (note == null) {
            throw new RuntimeException("笔记不存在");
        }
        
        // 更新浏览次数
        updateViewCount(id);
        
        // 转换为VO
        NoteVO noteVO = new NoteVO();
        BeanUtils.copyProperties(note, noteVO);
        
        // 设置是否点赞
        LambdaQueryWrapper<NoteLike> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(NoteLike::getNoteId, id).eq(NoteLike::getUserId, userId);
        boolean liked = noteLikeService.count(wrapper) > 0;
        noteVO.setLiked(liked);
        
        // 获取标签列表
        noteVO.setTagList(getNoteTagList(id));
        
        return noteVO;
    }
    
    /**
     * 获取笔记详情 - 外部传入用户ID
     */
    @Override
    @DataCache(prefix = CACHE_NOTE_PREFIX, key = "#id + ':' + #userId", expireTime = CacheConstants.TTL_SECONDS_ARTICLE)
    public NoteVO getNoteDetail(String id, String userId) {
        Note note = getById(id);
        if (note == null) {
            throw new RuntimeException("笔记不存在");
        }
        
        // 更新浏览次数
        updateViewCount(id);
        
        // 转换为VO
        NoteVO noteVO = new NoteVO();
        BeanUtils.copyProperties(note, noteVO);
        
        // 设置是否点赞
        if (userId != null) {
            LambdaQueryWrapper<NoteLike> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(NoteLike::getNoteId, id).eq(NoteLike::getUserId, userId);
            boolean liked = noteLikeService.count(wrapper) > 0;
            noteVO.setLiked(liked);
        }
        
        // 获取标签列表
        noteVO.setTagList(getNoteTagList(id));
        
        return noteVO;
    }
    
    /**
     * 分页查询笔记列表
     */
    @Override
    public PageResult<NoteVO> notePage(NoteQuery query) {
        try {
            // 从SecurityUtils获取用户ID设置到query
            String userIdStr = SecurityUtils.getCurrentUserId();
            
            // 处理用户未登录的情况（anonymousUser）
            if (StringUtils.isNotBlank(userIdStr) && !"anonymousUser".equals(userIdStr)) {
                try {
                    Long userId = Long.parseLong(userIdStr);
                    query.setUserId(userId);
                } catch (NumberFormatException e) {
                    log.error("用户ID格式错误，无法转换为Long类型: {}", userIdStr);
                    // 错误情况下不设置userId，继续查询公开笔记
                }
            }
            
            Page<Note> page = query.toPage();
            
            // 构建查询条件并执行查询
            Page<Note> notePage = lambdaQuery()
                .in(query.getNoteIds() != null && !query.getNoteIds().isEmpty(), Note::getId, query.getNoteIds())
                .eq(query.getUserId() != null, Note::getUserId, query.getUserId())
                .eq(query.getCourseId() != null, Note::getCourseId, query.getCourseId())
                .eq(StringUtils.isNotBlank(query.getCategoryId()), Note::getCategoryId, query.getCategoryId())
                .eq(query.getStatus() != null, Note::getStatus, query.getStatus())
                .like(StringUtils.isNotBlank(query.getTitle()), Note::getTitle, query.getTitle())
                .like(StringUtils.isNotBlank(query.getTags()), Note::getTags, query.getTags())
                .orderByDesc(Note::getCreateTime)
                .page(page);
            
            // 转换为NoteVO
            List<NoteVO> noteVOList = notePage.getRecords().stream()
                .map(note -> {
                    NoteVO noteVO = new NoteVO();
                    BeanUtils.copyProperties(note, noteVO);
                    // 获取标签列表
                    noteVO.setTagList(getNoteTagList(note.getId()));
                    return noteVO;
                })
                .collect(Collectors.toList());
            
            // 直接返回PageResult
            return PageResult.of(noteVOList, notePage.getTotal(), notePage.getCurrent(), notePage.getSize());
        } catch (Exception e) {
            log.error("分页查询笔记列表异常", e);
            return PageResult.of(new ArrayList<>(), 0L, query.getCurrent().longValue(), query.getSize().longValue());
        }
    }
    
    /**
     * 点赞/取消点赞 - 内部获取当前用户ID
     */
    @Override
    @Transactional
    @DataCacheEvict(prefix = CACHE_NOTE_PREFIX, key = "#noteId")
    public void toggleLike(String noteId) {
        // 直接在方法内获取用户ID
        String userId = SecurityUtils.getCurrentUserId();
        if (StringUtils.isBlank(userId)) {
            throw new UnauthorizedException("用户未登录");
        }
        
        // 检查笔记是否存在
        Note note = getById(noteId);
        if (note == null) {
            throw new RuntimeException("笔记不存在");
        }
        
        // 检查是否已点赞
        LambdaQueryWrapper<NoteLike> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(NoteLike::getNoteId, noteId)
               .eq(NoteLike::getUserId, userId);
        NoteLike noteLike = noteLikeService.getOne(wrapper);
        
        if (noteLike != null) {
            // 取消点赞
            noteLikeService.removeById(noteLike.getLikeId());
            updateLikeCount(noteId, -1);
        } else {
            // 添加点赞
            noteLike = new NoteLike();
            noteLike.setNoteId(noteId);
            noteLike.setUserId(userId);
            noteLikeService.save(noteLike);
            updateLikeCount(noteId, 1);
        }
    }
    
    /**
     * 点赞/取消点赞 - 外部传入用户ID
     */
    @Override
    @Transactional
    @DataCacheEvict(prefix = CACHE_NOTE_PREFIX, key = "#noteId + ':' + #userId")
    public void toggleLike(String noteId, String userId) {
        // 检查笔记是否存在
        Note note = getById(noteId);
        if (note == null) {
            throw new RuntimeException("笔记不存在");
        }
        
        // 检查是否已点赞
        LambdaQueryWrapper<NoteLike> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(NoteLike::getNoteId, noteId)
               .eq(NoteLike::getUserId, userId);
        NoteLike noteLike = noteLikeService.getOne(wrapper);
        
        if (noteLike != null) {
            // 取消点赞
            noteLikeService.removeById(noteLike.getLikeId());
            updateLikeCount(noteId, -1);
        } else {
            // 添加点赞
            noteLike = new NoteLike();
            noteLike.setNoteId(noteId);
            noteLike.setUserId(userId);
            noteLikeService.save(noteLike);
            updateLikeCount(noteId, 1);
        }
    }
    
    /**
     * 更新笔记状态
     */

    
    /**
     * 批量删除笔记
     */
    @Override
    @Transactional
    @DataCacheEvict(prefix = CACHE_NOTE_PREFIX, allEntries = true)
    public void deleteBatch(List<String> ids) {
        if (ids == null || ids.isEmpty()) {
            return;
        }

        log.info("批量删除笔记：{}", ids);
        
        try {
            // 分批处理，每次最多处理100条
            int batchSize = 100;
            int total = ids.size();
            
            for (int i = 0; i < total; i += batchSize) {
                int end = Math.min(i + batchSize, total);
                List<String> batch = ids.subList(i, end);
                
                // 转换ID格式并删除
                List<Long> longIds = batch.stream()
                        .filter(StringUtils::isNotBlank)
                        .map(Long::parseLong)
                        .collect(Collectors.toList());
                
                if (!longIds.isEmpty()) {
                    // 也可以考虑将笔记状态设置为删除状态，而不是物理删除
                    removeBatchByIds(longIds);
                    
                    // 删除相关的点赞记录
                    LambdaQueryWrapper<NoteLike> wrapper = new LambdaQueryWrapper<>();
                    wrapper.in(NoteLike::getNoteId, batch);
                    noteLikeService.remove(wrapper);
                }
            }
        } catch (Exception e) {
            log.error("批量删除笔记失败：{}", e.getMessage(), e);
            throw new RuntimeException("批量删除笔记失败", e);
        }
    }
    
    /**
     * 批量更新笔记状态
     */
    @Override
    @Transactional
    @DataCacheEvict(prefix = CACHE_NOTE_PREFIX, allEntries = true)
    public void batchUpdateStatus(List<String> ids, Integer status) {
        // 批量更新状态
        lambdaUpdate()
            .in(Note::getId, ids)
            .set(Note::getStatus, status)
            .update();
    }
    
    /**
     * 更新浏览次数
     */
    @Override
    @Transactional
    @DataCacheEvict(prefix = CACHE_NOTE_PREFIX, key = "#id")
    public void updateViewCount(String id) {
        // 使用SQL增加浏览次数
        lambdaUpdate()
            .eq(Note::getId, id)
            .setSql("view_count = view_count + 1")
            .update();
    }
    
    /**
     * 更新点赞数
     */
    @Override
    @Transactional
    @DataCacheEvict(prefix = CACHE_NOTE_PREFIX, key = "#id")
    public void updateLikeCount(String id, int delta) {
        // 使用SQL增加/减少点赞数
        lambdaUpdate()
            .eq(Note::getId, id)
            .setSql("like_count = like_count + (" + delta + ")")
            .update();
    }

    /**
     * 管理员添加或修改笔记
     *
     * @param note 笔记信息
     * @return 笔记VO
     */
    @Override
    @Transactional
    @DataCacheEvict(prefix = CACHE_NOTE_PREFIX, allEntries = true)
    public NoteVO addOrUpdateNoteByAdmin(Note note) {
        // 如果是修改操作
        if (StringUtils.isNotBlank(note.getId())) {
            Note existingNote = getById(note.getId());
            if (existingNote == null) {
                throw new RuntimeException("笔记不存在");
            }
            
            // 保存修改后的笔记信息
            updateById(note);
        } else {
            // 添加操作
            // 初始化计数器
            if (note.getViewCount() == null) {
                note.setViewCount(0);
            }
            if (note.getLikeCount() == null) {
                note.setLikeCount(0);
            }
            if (note.getCommentCount() == null) {
                note.setCommentCount(0);
            }
            save(note);
        }
        
        // 返回更新后的笔记信息
        NoteVO noteVO = new NoteVO();
        BeanUtils.copyProperties(getById(note.getId()), noteVO);
        return noteVO;
    }

    /**
     * 获取标签列表及使用统计
     */
    @Override
    @DataCache(prefix = CACHE_NOTE_PREFIX, key = CACHE_NOTE_TAGS_KEY, expireTime = 3600)
    public List<Map<String, Object>> getTagsWithCount() {
        // 使用Redis缓存获取标签统计
        String cacheKey = CACHE_NOTE_PREFIX + ":" + CACHE_NOTE_TAGS_KEY;
        List<Map<String, Object>> result = (List<Map<String, Object>>) redisUtils.get(cacheKey);
        if (result != null) {
            return result;
        }
        
        // 查询所有笔记的标签字段
        LambdaQueryWrapper<Note> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.select(Note::getTags).isNotNull(Note::getTags).ne(Note::getTags, "");
        List<Note> notes = list(queryWrapper);
        
        // 统计每个标签的使用次数
        Map<String, Integer> tagCountMap = new HashMap<>();
        for (Note note : notes) {
            String tags = note.getTags();
            if (StringUtils.isNotBlank(tags)) {
                String[] tagArray = tags.split(",");
                for (String tag : tagArray) {
                    tag = tag.trim();
                    if (StringUtils.isNotBlank(tag)) {
                        tagCountMap.put(tag, tagCountMap.getOrDefault(tag, 0) + 1);
                    }
                }
            }
        }
        
        // 转换为前端需要的格式
        result = tagCountMap.entrySet().stream()
            .map(entry -> {
                Map<String, Object> map = new HashMap<>(2);
                map.put("name", entry.getKey());
                map.put("value", entry.getValue());
                return map;
            })
            .collect(Collectors.toList());
        
        // 缓存结果
        redisUtils.set(cacheKey, result, 3600);
        return result;
    }
    
    /**
     * 获取笔记的标签列表
     */
    @Override
    public List<NoteTagVO> getNoteTagList(String noteId) {
        // 获取笔记关联的标签ID列表
        List<String> tagIds = noteTagRelationService.getTagIdsByNoteId(noteId);
        if (tagIds.isEmpty()) {
            return new ArrayList<>();
        }
        
        // 查询标签详情
        List<NoteTag> tags = noteTagService.listByIds(tagIds);
        
        // 转换为VO
        return tags.stream().map(tag -> {
            NoteTagVO vo = new NoteTagVO();
            BeanUtils.copyProperties(tag, vo);
            return vo;
        }).collect(Collectors.toList());
    }
    
    /**
     * 设置笔记标签
     */

}